home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / libogg / libvorbis-1.0rc3 / lib / info.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-27  |  16.8 KB  |  599 lines

  1. /********************************************************************
  2.  *                                                                  *
  3.  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
  4.  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
  5.  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6.  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  7.  *                                                                  *
  8.  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001             *
  9.  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
  10.  *                                                                  *
  11.  ********************************************************************
  12.  
  13.  function: maintain the info structure, info <-> header packets
  14.  last mod: $Id: info.c,v 1.52 2002/01/01 00:00:32 xiphmont Exp $
  15.  
  16.  ********************************************************************/
  17.  
  18. /* general handling of the header and the vorbis_info structure (and
  19.    substructures) */
  20.  
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <ogg/ogg.h>
  25. #include "vorbis/codec.h"
  26. #include "codec_internal.h"
  27. #include "codebook.h"
  28. #include "registry.h"
  29. #include "window.h"
  30. #include "psy.h"
  31. #include "misc.h"
  32. #include "os.h"
  33.  
  34. /* helpers */
  35. static int ilog2(unsigned int v){
  36.   int ret=0;
  37.   while(v>1){
  38.     ret++;
  39.     v>>=1;
  40.   }
  41.   return(ret);
  42. }
  43.  
  44. static void _v_writestring(oggpack_buffer *o,char *s, int bytes){
  45.  
  46.   while(bytes--){
  47.     oggpack_write(o,*s++,8);
  48.   }
  49. }
  50.  
  51. static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
  52.   while(bytes--){
  53.     *buf++=oggpack_read(o,8);
  54.   }
  55. }
  56.  
  57. void vorbis_comment_init(vorbis_comment *vc){
  58.   memset(vc,0,sizeof(*vc));
  59. }
  60.  
  61. void vorbis_comment_add(vorbis_comment *vc,char *comment){
  62.   vc->user_comments=_ogg_realloc(vc->user_comments,
  63.                 (vc->comments+2)*sizeof(*vc->user_comments));
  64.   vc->comment_lengths=_ogg_realloc(vc->comment_lengths,
  65.                       (vc->comments+2)*sizeof(*vc->comment_lengths));
  66.   vc->comment_lengths[vc->comments]=strlen(comment);
  67.   vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1);
  68.   strcpy(vc->user_comments[vc->comments], comment);
  69.   vc->comments++;
  70.   vc->user_comments[vc->comments]=NULL;
  71. }
  72.  
  73. void vorbis_comment_add_tag(vorbis_comment *vc, char *tag, char *contents){
  74.   char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */
  75.   strcpy(comment, tag);
  76.   strcat(comment, "=");
  77.   strcat(comment, contents);
  78.   vorbis_comment_add(vc, comment);
  79. }
  80.  
  81. /* This is more or less the same as strncasecmp - but that doesn't exist
  82.  * everywhere, and this is a fairly trivial function, so we include it */
  83. static int tagcompare(const char *s1, const char *s2, int n){
  84.   int c=0;
  85.   while(c < n){
  86.     if(toupper(s1[c]) != toupper(s2[c]))
  87.       return !0;
  88.     c++;
  89.   }
  90.   return 0;
  91. }
  92.  
  93. char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){
  94.   long i;
  95.   int found = 0;
  96.   int taglen = strlen(tag)+1; /* +1 for the = we append */
  97.   char *fulltag = alloca(taglen+ 1);
  98.  
  99.   strcpy(fulltag, tag);
  100.   strcat(fulltag, "=");
  101.   
  102.   for(i=0;i<vc->comments;i++){
  103.     if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
  104.       if(count == found)
  105.     /* We return a pointer to the data, not a copy */
  106.           return vc->user_comments[i] + taglen;
  107.       else
  108.     found++;
  109.     }
  110.   }
  111.   return NULL; /* didn't find anything */
  112. }
  113.  
  114. int vorbis_comment_query_count(vorbis_comment *vc, char *tag){
  115.   int i,count=0;
  116.   int taglen = strlen(tag)+1; /* +1 for the = we append */
  117.   char *fulltag = alloca(taglen+1);
  118.   strcpy(fulltag,tag);
  119.   strcat(fulltag, "=");
  120.  
  121.   for(i=0;i<vc->comments;i++){
  122.     if(!tagcompare(vc->user_comments[i], fulltag, taglen))
  123.       count++;
  124.   }
  125.  
  126.   return count;
  127. }
  128.  
  129. void vorbis_comment_clear(vorbis_comment *vc){
  130.   if(vc){
  131.     long i;
  132.     for(i=0;i<vc->comments;i++)
  133.       if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
  134.     if(vc->user_comments)_ogg_free(vc->user_comments);
  135.     if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
  136.     if(vc->vendor)_ogg_free(vc->vendor);
  137.   }
  138.   memset(vc,0,sizeof(*vc));
  139. }
  140.  
  141. /* blocksize 0 is guaranteed to be short, 1 is guarantted to be long.
  142.    They may be equal, but short will never ge greater than long */
  143. int vorbis_info_blocksize(vorbis_info *vi,int zo){
  144.   codec_setup_info *ci = vi->codec_setup;
  145.   return ci ? ci->blocksizes[zo] : -1;
  146. }
  147.  
  148. /* used by synthesis, which has a full, alloced vi */
  149. void vorbis_info_init(vorbis_info *vi){
  150.   memset(vi,0,sizeof(*vi));
  151.   vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
  152. }
  153.  
  154. void vorbis_info_clear(vorbis_info *vi){
  155.   codec_setup_info     *ci=vi->codec_setup;
  156.   int i;
  157.  
  158.   if(ci){
  159.  
  160.     for(i=0;i<ci->modes;i++)
  161.       if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
  162.  
  163.     for(i=0;i<ci->maps;i++) /* unpack does the range checking */
  164.       _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
  165.  
  166.     for(i=0;i<ci->times;i++) /* unpack does the range checking */
  167.       _time_P[ci->time_type[i]]->free_info(ci->time_param[i]);
  168.  
  169.     for(i=0;i<ci->floors;i++) /* unpack does the range checking */
  170.       _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
  171.     
  172.     for(i=0;i<ci->residues;i++) /* unpack does the range checking */
  173.       _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
  174.  
  175.     for(i=0;i<ci->books;i++){
  176.       if(ci->book_param[i]){
  177.     /* knows if the book was not alloced */
  178.     vorbis_staticbook_destroy(ci->book_param[i]);
  179.       }
  180.     }
  181.     
  182.     for(i=0;i<ci->psys;i++)
  183.       _vi_psy_free(ci->psy_param[i]);
  184.  
  185.     _ogg_free(ci);
  186.   }
  187.  
  188.   memset(vi,0,sizeof(*vi));
  189. }
  190.  
  191. /* Header packing/unpacking ********************************************/
  192.  
  193. static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
  194.   codec_setup_info     *ci=vi->codec_setup;
  195.   if(!ci)return(OV_EFAULT);
  196.  
  197.   vi->version=oggpack_read(opb,32);
  198.   if(vi->version!=0)return(OV_EVERSION);
  199.  
  200.   vi->channels=oggpack_read(opb,8);
  201.   vi->rate=oggpack_read(opb,32);
  202.  
  203.   vi->bitrate_upper=oggpack_read(opb,32);
  204.   vi->bitrate_nominal=oggpack_read(opb,32);
  205.   vi->bitrate_lower=oggpack_read(opb,32);
  206.  
  207.   ci->blocksizes[0]=1<<oggpack_read(opb,4);
  208.   ci->blocksizes[1]=1<<oggpack_read(opb,4);
  209.   
  210.   if(vi->rate<1)goto err_out;
  211.   if(vi->channels<1)goto err_out;
  212.   if(ci->blocksizes[0]<8)goto err_out; 
  213.   if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
  214.   
  215.   if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
  216.  
  217.   return(0);
  218.  err_out:
  219.   vorbis_info_clear(vi);
  220.   return(OV_EBADHEADER);
  221. }
  222.  
  223. static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
  224.   int i;
  225.   int vendorlen=oggpack_read(opb,32);
  226.   if(vendorlen<0)goto err_out;
  227.   vc->vendor=_ogg_calloc(vendorlen+1,1);
  228.   _v_readstring(opb,vc->vendor,vendorlen);
  229.   vc->comments=oggpack_read(opb,32);
  230.   if(vc->comments<0)goto err_out;
  231.   vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
  232.   vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
  233.         
  234.   for(i=0;i<vc->comments;i++){
  235.     int len=oggpack_read(opb,32);
  236.     if(len<0)goto err_out;
  237.     vc->comment_lengths[i]=len;
  238.     vc->user_comments[i]=_ogg_calloc(len+1,1);
  239.     _v_readstring(opb,vc->user_comments[i],len);
  240.   }      
  241.   if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
  242.  
  243.   return(0);
  244.  err_out:
  245.   vorbis_comment_clear(vc);
  246.   return(OV_EBADHEADER);
  247. }
  248.  
  249. /* all of the real encoding details are here.  The modes, books,
  250.    everything */
  251. static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
  252.   codec_setup_info     *ci=vi->codec_setup;
  253.   int i;
  254.   if(!ci)return(OV_EFAULT);
  255.  
  256.   /* codebooks */
  257.   ci->books=oggpack_read(opb,8)+1;
  258.   /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/
  259.   for(i=0;i<ci->books;i++){
  260.     ci->book_param[i]=_ogg_calloc(1,sizeof(*ci->book_param[i]));
  261.     if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
  262.   }
  263.  
  264.   /* time backend settings */
  265.   ci->times=oggpack_read(opb,6)+1;
  266.   /*ci->time_type=_ogg_malloc(ci->times*sizeof(*ci->time_type));*/
  267.   /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/
  268.   for(i=0;i<ci->times;i++){
  269.     ci->time_type[i]=oggpack_read(opb,16);
  270.     if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out;
  271.     ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb);
  272.     if(!ci->time_param[i])goto err_out;
  273.   }
  274.  
  275.   /* floor backend settings */
  276.   ci->floors=oggpack_read(opb,6)+1;
  277.   /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/
  278.   /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/
  279.   for(i=0;i<ci->floors;i++){
  280.     ci->floor_type[i]=oggpack_read(opb,16);
  281.     if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
  282.     ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
  283.     if(!ci->floor_param[i])goto err_out;
  284.   }
  285.  
  286.   /* residue backend settings */
  287.   ci->residues=oggpack_read(opb,6)+1;
  288.   /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/
  289.   /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/
  290.   for(i=0;i<ci->residues;i++){
  291.     ci->residue_type[i]=oggpack_read(opb,16);
  292.     if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
  293.     ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
  294.     if(!ci->residue_param[i])goto err_out;
  295.   }
  296.  
  297.   /* map backend settings */
  298.   ci->maps=oggpack_read(opb,6)+1;
  299.   /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/
  300.   /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/
  301.   for(i=0;i<ci->maps;i++){
  302.     ci->map_type[i]=oggpack_read(opb,16);
  303.     if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
  304.     ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
  305.     if(!ci->map_param[i])goto err_out;
  306.   }
  307.   
  308.   /* mode settings */
  309.   ci->modes=oggpack_read(opb,6)+1;
  310.   /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/
  311.   for(i=0;i<ci->modes;i++){
  312.     ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i]));
  313.     ci->mode_param[i]->blockflag=oggpack_read(opb,1);
  314.     ci->mode_param[i]->windowtype=oggpack_read(opb,16);
  315.     ci->mode_param[i]->transformtype=oggpack_read(opb,16);
  316.     ci->mode_param[i]->mapping=oggpack_read(opb,8);
  317.  
  318.     if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
  319.     if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
  320.     if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
  321.   }
  322.   
  323.   if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
  324.  
  325.   return(0);
  326.  err_out:
  327.   vorbis_info_clear(vi);
  328.   return(OV_EBADHEADER);
  329. }
  330.  
  331. /* The Vorbis header is in three packets; the initial small packet in
  332.    the first page that identifies basic parameters, a second packet
  333.    with bitstream comments and a third packet that holds the
  334.    codebook. */
  335.  
  336. int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
  337.   oggpack_buffer opb;
  338.   
  339.   if(op){
  340.     oggpack_readinit(&opb,op->packet,op->bytes);
  341.  
  342.     /* Which of the three types of header is this? */
  343.     /* Also verify header-ness, vorbis */
  344.     {
  345.       char buffer[6];
  346.       int packtype=oggpack_read(&opb,8);
  347.       memset(buffer,0,6);
  348.       _v_readstring(&opb,buffer,6);
  349.       if(memcmp(buffer,"vorbis",6)){
  350.     /* not a vorbis header */
  351.     return(OV_ENOTVORBIS);
  352.       }
  353.       switch(packtype){
  354.       case 0x01: /* least significant *bit* is read first */
  355.     if(!op->b_o_s){
  356.       /* Not the initial packet */
  357.       return(OV_EBADHEADER);
  358.     }
  359.     if(vi->rate!=0){
  360.       /* previously initialized info header */
  361.       return(OV_EBADHEADER);
  362.     }
  363.  
  364.     return(_vorbis_unpack_info(vi,&opb));
  365.  
  366.       case 0x03: /* least significant *bit* is read first */
  367.     if(vi->rate==0){
  368.       /* um... we didn't get the initial header */
  369.       return(OV_EBADHEADER);
  370.     }
  371.  
  372.     return(_vorbis_unpack_comment(vc,&opb));
  373.  
  374.       case 0x05: /* least significant *bit* is read first */
  375.     if(vi->rate==0 || vc->vendor==NULL){
  376.       /* um... we didn;t get the initial header or comments yet */
  377.       return(OV_EBADHEADER);
  378.     }
  379.  
  380.     return(_vorbis_unpack_books(vi,&opb));
  381.  
  382.       default:
  383.     /* Not a valid vorbis header type */
  384.     return(OV_EBADHEADER);
  385.     break;
  386.       }
  387.     }
  388.   }
  389.   return(OV_EBADHEADER);
  390. }
  391.  
  392. /* pack side **********************************************************/
  393.  
  394. static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
  395.   codec_setup_info     *ci=vi->codec_setup;
  396.   if(!ci)return(OV_EFAULT);
  397.  
  398.   /* preamble */  
  399.   oggpack_write(opb,0x01,8);
  400.   _v_writestring(opb,"vorbis", 6);
  401.  
  402.   /* basic information about the stream */
  403.   oggpack_write(opb,0x00,32);
  404.   oggpack_write(opb,vi->channels,8);
  405.   oggpack_write(opb,vi->rate,32);
  406.  
  407.   oggpack_write(opb,vi->bitrate_upper,32);
  408.   oggpack_write(opb,vi->bitrate_nominal,32);
  409.   oggpack_write(opb,vi->bitrate_lower,32);
  410.  
  411.   oggpack_write(opb,ilog2(ci->blocksizes[0]),4);
  412.   oggpack_write(opb,ilog2(ci->blocksizes[1]),4);
  413.   oggpack_write(opb,1,1);
  414.  
  415.   return(0);
  416. }
  417.  
  418. static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
  419.   char temp[]="Xiphophorus libVorbis I 20011231";
  420.   int bytes = strlen(temp);
  421.  
  422.   /* preamble */  
  423.   oggpack_write(opb,0x03,8);
  424.   _v_writestring(opb,"vorbis", 6);
  425.  
  426.   /* vendor */
  427.   oggpack_write(opb,bytes,32);
  428.   _v_writestring(opb,temp, bytes);
  429.   
  430.   /* comments */
  431.  
  432.   oggpack_write(opb,vc->comments,32);
  433.   if(vc->comments){
  434.     int i;
  435.     for(i=0;i<vc->comments;i++){
  436.       if(vc->user_comments[i]){
  437.     oggpack_write(opb,vc->comment_lengths[i],32);
  438.     _v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]);
  439.       }else{
  440.     oggpack_write(opb,0,32);
  441.       }
  442.     }
  443.   }
  444.   oggpack_write(opb,1,1);
  445.  
  446.   return(0);
  447. }
  448.  
  449. static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
  450.   codec_setup_info     *ci=vi->codec_setup;
  451.   int i;
  452.   if(!ci)return(OV_EFAULT);
  453.  
  454.   oggpack_write(opb,0x05,8);
  455.   _v_writestring(opb,"vorbis", 6);
  456.  
  457.   /* books */
  458.   oggpack_write(opb,ci->books-1,8);
  459.   for(i=0;i<ci->books;i++)
  460.     if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out;
  461.  
  462.   /* times */
  463.   oggpack_write(opb,ci->times-1,6);
  464.   for(i=0;i<ci->times;i++){
  465.     oggpack_write(opb,ci->time_type[i],16);
  466.     _time_P[ci->time_type[i]]->pack(ci->time_param[i],opb);
  467.   }
  468.  
  469.   /* floors */
  470.   oggpack_write(opb,ci->floors-1,6);
  471.   for(i=0;i<ci->floors;i++){
  472.     oggpack_write(opb,ci->floor_type[i],16);
  473.     _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
  474.   }
  475.  
  476.   /* residues */
  477.   oggpack_write(opb,ci->residues-1,6);
  478.   for(i=0;i<ci->residues;i++){
  479.     oggpack_write(opb,ci->residue_type[i],16);
  480.     _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb);
  481.   }
  482.  
  483.   /* maps */
  484.   oggpack_write(opb,ci->maps-1,6);
  485.   for(i=0;i<ci->maps;i++){
  486.     oggpack_write(opb,ci->map_type[i],16);
  487.     _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb);
  488.   }
  489.  
  490.   /* modes */
  491.   oggpack_write(opb,ci->modes-1,6);
  492.   for(i=0;i<ci->modes;i++){
  493.     oggpack_write(opb,ci->mode_param[i]->blockflag,1);
  494.     oggpack_write(opb,ci->mode_param[i]->windowtype,16);
  495.     oggpack_write(opb,ci->mode_param[i]->transformtype,16);
  496.     oggpack_write(opb,ci->mode_param[i]->mapping,8);
  497.   }
  498.   oggpack_write(opb,1,1);
  499.  
  500.   return(0);
  501. err_out:
  502.   return(-1);
  503.  
  504. int vorbis_commentheader_out(vorbis_comment *vc,
  505.                           ogg_packet *op){
  506.  
  507.   oggpack_buffer opb;
  508.  
  509.   oggpack_writeinit(&opb);
  510.   if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL;
  511.  
  512.   op->packet = _ogg_malloc(oggpack_bytes(&opb));
  513.   memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
  514.  
  515.   op->bytes=oggpack_bytes(&opb);
  516.   op->b_o_s=0;
  517.   op->e_o_s=0;
  518.   op->granulepos=0;
  519.  
  520.   return 0;
  521. }
  522.  
  523. int vorbis_analysis_headerout(vorbis_dsp_state *v,
  524.                   vorbis_comment *vc,
  525.                   ogg_packet *op,
  526.                   ogg_packet *op_comm,
  527.                   ogg_packet *op_code){
  528.   int ret=OV_EIMPL;
  529.   vorbis_info *vi=v->vi;
  530.   oggpack_buffer opb;
  531.   backend_lookup_state *b=v->backend_state;
  532.  
  533.   if(!b){
  534.     ret=OV_EFAULT;
  535.     goto err_out;
  536.   }
  537.  
  538.   /* first header packet **********************************************/
  539.  
  540.   oggpack_writeinit(&opb);
  541.   if(_vorbis_pack_info(&opb,vi))goto err_out;
  542.  
  543.   /* build the packet */
  544.   if(b->header)_ogg_free(b->header);
  545.   b->header=_ogg_malloc(oggpack_bytes(&opb));
  546.   memcpy(b->header,opb.buffer,oggpack_bytes(&opb));
  547.   op->packet=b->header;
  548.   op->bytes=oggpack_bytes(&opb);
  549.   op->b_o_s=1;
  550.   op->e_o_s=0;
  551.   op->granulepos=0;
  552.  
  553.   /* second header packet (comments) **********************************/
  554.  
  555.   oggpack_reset(&opb);
  556.   if(_vorbis_pack_comment(&opb,vc))goto err_out;
  557.  
  558.   if(b->header1)_ogg_free(b->header1);
  559.   b->header1=_ogg_malloc(oggpack_bytes(&opb));
  560.   memcpy(b->header1,opb.buffer,oggpack_bytes(&opb));
  561.   op_comm->packet=b->header1;
  562.   op_comm->bytes=oggpack_bytes(&opb);
  563.   op_comm->b_o_s=0;
  564.   op_comm->e_o_s=0;
  565.   op_comm->granulepos=0;
  566.  
  567.   /* third header packet (modes/codebooks) ****************************/
  568.  
  569.   oggpack_reset(&opb);
  570.   if(_vorbis_pack_books(&opb,vi))goto err_out;
  571.  
  572.   if(b->header2)_ogg_free(b->header2);
  573.   b->header2=_ogg_malloc(oggpack_bytes(&opb));
  574.   memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
  575.   op_code->packet=b->header2;
  576.   op_code->bytes=oggpack_bytes(&opb);
  577.   op_code->b_o_s=0;
  578.   op_code->e_o_s=0;
  579.   op_code->granulepos=0;
  580.  
  581.   oggpack_writeclear(&opb);
  582.   return(0);
  583.  err_out:
  584.   oggpack_writeclear(&opb);
  585.   memset(op,0,sizeof(*op));
  586.   memset(op_comm,0,sizeof(*op_comm));
  587.   memset(op_code,0,sizeof(*op_code));
  588.  
  589.   if(b->header)_ogg_free(b->header);
  590.   if(b->header1)_ogg_free(b->header1);
  591.   if(b->header2)_ogg_free(b->header2);
  592.   b->header=NULL;
  593.   b->header1=NULL;
  594.   b->header2=NULL;
  595.   return(ret);
  596. }
  597.  
  598.